package com.lebang.service.task.impl;


import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lebang.common.util.ShowDateUtil;
import com.lebang.component.RedisClient;
import com.lebang.component.RedisSdkClient;
import com.lebang.entity.RequestHeaders;
import com.lebang.entity.member.LbbMember;
import com.lebang.entity.member.LbbMemberRecord;
import com.lebang.entity.task.TaskComments;
import com.lebang.entity.task.TaskCommentsDetail;
import com.lebang.entity.task.TaskScreenshot;
import com.lebang.example.TaskCommentsExample;
import com.lebang.mapper.*;
import com.lebang.model.TaskInitModel;
import com.lebang.model.Whether;
import com.lebang.model.enums.Booleans;
import com.lebang.model.enums.Status;
import com.lebang.model.enums.TaskEnableResultEnum;
import com.lebang.model.enums.buss.RecordStatus;
import com.lebang.model.enums.buss.TaskCategory;
import com.lebang.model.enums.buss.TaskStatus;
import com.lebang.model.enums.buss.UserStatus;
import com.lebang.model.recordback.RecordCallBack;
import com.lebang.model.taskback.CommonCallBack;
import com.lebang.model.taskback.Detail;
import com.lebang.model.taskback.Record;
import com.lebang.model.vo.buss.TaskSearchVo;
import com.lebang.service.MemberNoticeService;
import com.lebang.service.TaskInRedisService;
import com.lebang.service.buss.MemberRecordService;
import com.lebang.service.buss.WalletService;
import com.lebang.service.task.TaskService;
import com.lebangweb.common.DateUtil;
import com.lebangweb.common.TextUtil;
import com.lebangweb.common.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.OutputStream;
import java.time.LocalDateTime;
import java.util.*;


/**
 * @Author: hwq
 * @Date: 2019/8/6 10:47
 * @Version 1.0
 */
@Service(value = "commentsTaskService")
public class CommentsServiceImpl implements TaskService<TaskComments> {
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private TaskInRedisService taskInRedisService;

    @Autowired
    private TaskCommentsMapper taskCommentsMapper;

    @Autowired
    private MemberRecordService memberRecordService;
    @Autowired
    private TaskCommentsDetailMapper detailMapper;
    @Autowired
    private WalletService walletService;
    @Autowired
    private MemberNoticeService memberNoticeService;

    @Autowired
    private LbbMemberRecordMapper lbbMemberRecordMapper;

    @Autowired
    private LbbMemberMapper lbbMemberMapper;

    @Autowired
    private TaskScreenshotMapper taskScreenshotMapper;

    @Autowired
    private RedisSdkClient redisSdkClient;


    public static final String TASK_COMMENTS_AMOUNT = "task_comments_amount";


    /**
     * 领取任务
     *
     * @param memberId      会员id(唯一)
     * @param task          任务 (唯一)
     * @param requsetHeader 其他头部参数
     * @param orderId       订单id
     * @return RecordStatus record status
     */
    @Override
    public RecordStatus pull(String memberId, TaskComments task, RequestHeaders requsetHeader, String orderId, String taskId) {
        // redis 里查看任务量
        int count = taskInRedisService.getTaskAmount(TASK_COMMENTS_AMOUNT, task.getTaskId());
        if (count <= 0) {
            return RecordStatus.OUT_OF_STOCK;
        }
        // 用户是否做过
        LbbMemberRecord record = memberRecordService.checkRecord(memberId, task.getTaskId(), TaskCategory.Comments.name());
        if (record != null) {
            return RecordStatus.EXIST;
        }

        TaskCommentsDetail detail = detailMapper.selectByCommentsId(task.getId());
        if (detail == null) {
            return RecordStatus.COMMENT_HAS_NO;
        }
        detail.setMemberId(memberId);
        detail.setStatus(1);
        detail.setModifyTime(new java.util.Date());
        detailMapper.updateByPrimaryKeySelective(detail);
        //领取成功redis任务量-1
        taskInRedisService.taskAmountSubtract(TASK_COMMENTS_AMOUNT, task.getTaskId());
        int t = memberRecordService.insertRecord(TaskCategory.Comments, task.getTaskId(), memberId, requsetHeader, TaskStatus.WaitSumbit, "", detail.getId().toString(), Booleans.True, 0, task.getWorth(), task.getIncrease(), task.getType(), task.getTitle());
        //监听任务30分钟释放
        taskInRedisService.recordAdd(t);
        //已领取数量+1
        if (task.getWaitTime() != 0 && task.getWaitCount() != 0) {
            long pullCount = taskInRedisService.recordAddRedBook(task.getTaskId());
            if (pullCount >= task.getWaitCount()) {
                taskInRedisService.addCheckRedBookByTaksId(task.getTaskId(), task.getWaitTime());
            }
        }

        return RecordStatus.PULL_SUCCESS;
    }

    /**
     * 提交任务
     *
     * @param memberId 会员id(唯一)
     * @param record   任务 (唯一)
     * @param task     任务类型
     * @param result   用户提交信息
     * @param sex      是否作弊
     * @return the record status
     */
    @Override
    public RecordStatus push(String memberId, LbbMemberRecord record, TaskComments task, String result, Integer sex) {
        record.setResult(result);
        record.setSubmitTime(new Date());
        record.setStatus(TaskStatus.WaitCheckout);
        if (sex != null) {
            record.setSex(sex);
        }
        /*提交任务修改状态*/
        int i = memberRecordService.updateByPrimaryKeySelective(record);
        if (i == 0) {
            return RecordStatus.FAIL;
        }
        String desc = "恭喜！任务“{title}”已提交，小姐姐正在努力审核!";
        desc = desc.replace("{title}", task.getTitle());
        memberNoticeService.notice(record, TaskCategory.Comments.getTitle(), desc);
        if (record.getRedo() != null) {
            if (record.getRedo() == 0) {
                taskInRedisService.recordDel(record.getId().intValue());
            }
        }
        if (task.getLessTime() != 0) {
            taskInRedisService.addRedBookFiter(memberId, task.getLessTime());
        }
        return RecordStatus.PUSH_SUCCESS;
    }

    /**
     * 重做任务
     *
     * @param memberId 会员id(唯一)
     * @param record   the record
     * @param task     任务 (唯一)
     * @return the record status
     */
    @Override
    public RecordStatus redo(String memberId, LbbMemberRecord record, TaskComments task) {
        if (record.getRedo() == null) {
            record.setRedo(0);
        }

        TaskScreenshot taskScreenshot = taskScreenshotMapper.selectByTaskId(task.getTaskId());
        if(taskScreenshot!=null){
            if(taskScreenshot.getFailTimes()!=-1&&taskScreenshot.getFailTimes()<=(record.getRedo())){
                return RecordStatus.REDO_MAX;
            }
        }

        record.setRedo(record.getRedo()+1);
        record.setStatus(TaskStatus.WaitSumbit);
        record.setCreateTime(new Date());
        taskInRedisService.recordAdd(record.getId().intValue());
        record.setHurryTime(null);
        record.setSubmitTime(new Date());
        record.setResult("");
        memberRecordService.updateByPrimaryKeySelective(record);
        taskInRedisService.taskAmountSubtract(TASK_COMMENTS_AMOUNT, task.getTaskId());

        //已领取数量+1
        if (task.getWaitTime() != 0 && task.getWaitCount() != 0) {
            long pullCount = taskInRedisService.recordAddRedBook(task.getTaskId());
            if (pullCount >= task.getWaitCount()) {
                taskInRedisService.addCheckRedBookByTaksId(task.getTaskId(), task.getWaitTime());
            }
        }
        return RecordStatus.REDO_SUCCESS;
    }

    /**
     * 催审任务
     *
     * @param memberId 会员id(唯一)
     * @param record   the record
     * @param task     任务 (唯一)
     * @return the record status
     */
    @Override
    public RecordStatus urgentTask(String memberId, LbbMemberRecord record, TaskComments task) {
        List<String> id = new ArrayList<>(1);
        id.add(record.getId().toString());
        this.examineAndVerify(id, "", "任务成功", "",1);
        return RecordStatus.CALL_SUCCESS;
    }

    /**
     * 任务详情
     *
     * @param taskId 任务id (唯一)
     * @return the t
     */
    @Override
    public TaskComments taskInfoByTaskId(String taskId) {
        return taskCommentsMapper.getByTaskId(taskId);
    }

    /**
     * 任务详情
     *
     * @param id 自增id (唯一)
     * @return the t
     */
    @Override
    public TaskComments taskInfoById(Integer id) {
        return taskCommentsMapper.selectByPrimaryKey(id);
    }

    /**
     * 用户任务详情,APP 端取任务详情
     *
     * @param task     任务
     * @param record   任务记录
     * @param memberId the member id
     * @param orderId  the order id
     * @return the common call back
     * @throws Exception the exception
     */
    @Override
    public CommonCallBack taskDetail(TaskComments task, LbbMemberRecord record, LbbMember memberId, String orderId) throws Exception {
        CommonCallBack commonCallBack = new CommonCallBack();
        Record reco = new Record();
        Detail detail = new Detail();
        // 获取任务量完成情况
        int amount = taskInRedisService.getTaskAmount(TASK_COMMENTS_AMOUNT, task.getTaskId());

        String userStatus = UserStatus.Allow.name();
        if (record != null) {
            // 如果做过不允许再做
            userStatus = UserStatus.Disallow.name();
            if (!record.getStatus().equals(TaskStatus.WaitSumbit)) {
                commonCallBack.setMemberResult(JSONArray.parseArray(record.getResult()));
            }
            commonCallBack.setType(record.getRewordType());
            commonCallBack.setUserMoney(record.getUserMoney());
        } else {
            record = new LbbMemberRecord();
            record.setCreateTime(new Date());
            record.setStatus(TaskStatus.None);
            commonCallBack.setType(task.getType().getIndex());
            commonCallBack.setUserMoney(task.getWorth());
        }
        if (!TextUtil.isEmpty(task.getMission())) {
            List<String> stringList = Arrays.asList(task.getMission().split("#"));
            detail.setIsMission(true);
            detail.setMissionList(stringList);
        }
        detail.setContents(JSONArray.parseArray(task.getContents()));
        detail.setPkg(task.getPkg());
        detail.setAmount(amount);
        detail.setIcon(task.getIcon());
        detail.setTitle(task.getTitle());
        detail.setLabel(task.getLabel());
        detail.setMedia(task.getMedia());
        detail.setUserStatus(userStatus);

        reco.setEndTime(ShowDateUtil.afterMinute(record.getCreateTime(), 30));

        reco.setResult(record.getResult() == null ? "" : record.getResult());
        reco.setStatus(record.getStatus().name());
        reco.setRemark(record.getRemark());
        reco.setSubmitTime(record.getSubmitTime() == null ? "" : DateUtil.dateToString(record.getSubmitTime(), "yyyy-MM-dd HH:mm:ss"));
        commonCallBack.setCategory(TaskCategory.Comments.name());
        commonCallBack.setTaskid(task.getTaskId());
        commonCallBack.setTaskTime(task.getTaskTime());
        commonCallBack.setAuditTime(task.getAuditTime());
        commonCallBack.setRedoStatus(task.getRedo());
        if (task.getRedo() == null) {
            task.setRedo(0);
        }
        if (record.getHurryTime() == null) {

            commonCallBack.setHurryTime(0);
        } else {
            commonCallBack.setHurryTime(1);
        }
        if (record.getRedo() == null) {
            record.setRedo(0);
        }
        if (record.getSubmitTime() != null && record.getCreateTime() != null) {
            commonCallBack.setOverTime(ShowDateUtil.getDatePoor(record.getSubmitTime(), record.getCreateTime()));
        } else {
            commonCallBack.setOverTime("0");
        }
        commonCallBack.setRedocount(record.getRedo());
        commonCallBack.setRecord(reco);
        commonCallBack.setDetail(detail);
        return commonCallBack;

    }

    /**
     * 检测用户是否可以做这个任务
     *
     * @param taskid 任务taskId
     * @param imei   设备imei
     * @param userid 用户id
     * @return the TaskEnableResultEnum
     */
    @Override
    public TaskEnableResultEnum checkTaskEnableDoForUser(String taskid, String imei, String userid) {
        TaskComments lbbCommon = taskCommentsMapper.getByTaskId(taskid);
        if (lbbCommon == null || lbbCommon.getStatus().equals(Status.Off.getIndex())) {
            return TaskEnableResultEnum.FAIL_NOT_EXITS;
        }
        if (lbbCommon.getWaitCount() != 0 && lbbCommon.getWaitTime() != 0) {
            if (taskInRedisService.checkRedBookFiter(userid)) {
                return TaskEnableResultEnum.FAIL_TASK_END;
            }
        }
        if (lbbCommon.getLessTime() != 0) {
            if (taskInRedisService.checkRedBookByTaksId(taskid)) {
                return TaskEnableResultEnum.FAIL_TASK_END;
            }
        }
        return TaskEnableResultEnum.SUCCESS;
    }

    /**
     * 添加任务
     *
     * @param task the task
     * @return int
     */
    @Override
    public int insertTask(TaskComments task) {
        task.setTaskId(UUID.randomUUID().toString());
        task.setHasDeleted(Whether.NO.getDbIndex());
        task.setCreateTime(new java.util.Date());
        task.setModifyTime(new java.util.Date());
        task.setStatus(1);
        return taskCommentsMapper.insertSelective(task);
    }

    /**
     * 修改任务
     *
     * @param task the task
     * @return int
     */
    @Override
    public int updateTask(TaskComments task) {
        task.setModifyTime(new java.util.Date());
        return taskCommentsMapper.updateByPrimaryKeySelective(task);
    }

    /**
     * 删除任务
     *
     * @param task the task
     * @return int
     */
    @Override
    public int deleteTask(TaskComments task) {
        task.setHasDeleted(1);
        return taskCommentsMapper.updateByPrimaryKeySelective(task);
    }

    /**
     * 审核任务
     *
     * @param list   the list
     * @param tab    the tab
     * @param status the status
     * @param remark the remark
     * @return the int
     */
    @Override

    public int examineAndVerify(List<String> list, String tab, String status, String remark,Integer multiple) {
        String uuid = UUIDUtil.M();
        //boolean lock = redisClient.tryGetDistributedLock("lock:comments", uuid, 30000);
        boolean lock = redisSdkClient.tryGetDistributedLock("lock:comments", uuid, 30000);
        try {
            if (!lock) {
                return -1;
            }
            List<LbbMemberRecord> recordList = lbbMemberRecordMapper.findCheckListByid(list);

            for (LbbMemberRecord record : recordList) {
                if (record.getStatus().equals(TaskStatus.CheckSuccess)) {
                    continue;
                }
                record.setStatus(TaskStatus.getByTitle(status));
                TaskComments task = this.taskInfoByTaskId(record.getTaskId());
                record.setStatus(TaskStatus.getByTitle(status));
                if (record.getStatus().equals(TaskStatus.CheckFailure)) {
                    record.setRemark(remark);
                }
                record.setCheckTime(new Date());
                memberRecordService.updateByPrimaryKeySelective(record);
                if (record.getStatus().equals(TaskStatus.CheckSuccess)) {
                    // 计算奖励
                    Integer amount;
                    if (record.getUserMoney().equals(0)) {
                        amount = task.getWorth();
                    } else {
                        amount = record.getUserMoney();
                    }
                    walletService.income(record.getMemberId(), record, TaskCategory.Comments, record.getTaskId(), task.getTitle(), amount*multiple);
                    task.setSuccessCount(task.getSuccessCount() + 1);
                    task.setTodayAmount(task.getTodayAmount() + 1);
                    memberNoticeService.notice(record, task.getTitle(), "任务通知:提交的任务审核成功!");
                } else {
                    task.setFailCount(task.getFailCount() + 1);
                    memberNoticeService.notice(record, task.getTitle(), "对不起，您提交的不符合要求，审核失败!");
                    //审核失败解除用户的过滤
                    taskInRedisService.cleanRedBookFiter(record.getMemberId());
                }
                this.updateTask(task);
            }
            return 1;
        } catch (Exception e) {
            e.printStackTrace();

            return 0;
        } finally {
            //redisClient.releaseDistributedLock("lock:comments", uuid);
            redisSdkClient.releaseDistributedLock("lock:comments", uuid);
        }
    }

    /**
     * @param memberId     用户的ID
     * @param page         分页，第几页
     * @param size         条数
     * @param brand        手机的品牌渠道
     * @param showHomePage 是否在首面显示
     * @param imei
     * @param params
     * @return 任务列表
     */
    @Override
    public List<RecordCallBack> showListForApp(String memberId, Integer page, Integer size, String brand, Integer showHomePage, String imei, String params) {
        return null;
    }

    /**
     * 任务列表
     *
     * @param page  页数
     * @param limit 条数
     * @return List list
     */
    @Override
    public List<TaskComments> taskList(Integer page, Integer limit) {
        TaskCommentsExample example = new TaskCommentsExample();
        if(!TextUtil.isEmpty(page,limit)){
            example.setOffset((long) ((page-1)*limit));
            example.setLimit(limit);
        }
        return taskCommentsMapper.selectByExample(example);
    }

    /**
     * 列表
     *
     * @param vo the vo
     * @return the map
     * <p>
     */
    @Override
    public Map<String, Object> list(TaskSearchVo vo) {
        return null;
    }


    @Override
    public Boolean exportTaskRecode(String taskId, OutputStream outputStream, List<TaskStatus> taskStatusList) {
        TaskComments lbbCommon = taskCommentsMapper.getByTaskId(taskId);
        if (lbbCommon == null) {
            return false;
        }
        String contents = lbbCommon.getContents();

        ExcelWriter writer = new ExcelWriter(outputStream, ExcelTypeEnum.XLSX, true);
        Sheet sheet1 = new Sheet(1, 0);
        sheet1.setSheetName("第一个sheet");
        List<LbbMemberRecord> records = new ArrayList<>();
        for (TaskStatus t : taskStatusList) {
            records.addAll(memberRecordService.getRecord(taskId, t, TaskCategory.Comments));
        }
        // 设置标题
        Table table = new Table(1);
        List<List<String>> titles = new ArrayList<>();
        titles.add(Collections.singletonList("审核结果"));
        titles.add(Collections.singletonList("任务时间"));
        titles.add(Collections.singletonList("手机号"));
        titles.add(Collections.singletonList("设备标识"));
        int step = 1;
        if (contents != null && !TextUtil.isEmpty(contents)) {
            JSONArray jsonArray = JSONArray.parseArray(contents);
            for (Object object : jsonArray) {
                JSONObject jsonObject = (JSONObject) object;
                if ("image".equals(jsonObject.getString("type"))) {
                    titles.add(Collections.singletonList("步骤" + step + "-图片"));
                } else if ("input".equals(jsonObject.getString("type"))) {
                    titles.add(Collections.singletonList("步骤" + step + "-输入"));
                }
            }
        }
        table.setHead(titles);
        List<List<String>> datalist = new ArrayList<>();

        for (LbbMemberRecord record : records) {
            LbbMember member = lbbMemberMapper.getMemberByMemberId(record.getMemberId());
            List<String> item = new ArrayList<>();

            item.add(record.getStatus().getTitle());
            item.add(DateUtil.dateToString(record.getCreateTime(), "yyyy-MM-dd HH:mm"));
            item.add(member.getPhone());
            item.add(record.getImei());

            String result = record.getResult();
            JSONArray jsonArrayResult = JSONArray.parseArray(result);

            for (Object oresult : jsonArrayResult) {
                JSONObject rt = (JSONObject) oresult;
                if ("image".equals(rt.getString("type"))) {
                    item.add(rt.getJSONObject("resultImage").getString("image"));
                } else if ("input".equals(rt.getString("type"))) {
                    item.add(rt.getJSONObject("resultInput").getString("image"));
                }
            }
            datalist.add(item);
        }

        writer.write0(datalist, sheet1, table);
        writer.finish();

        return true;
    }

    @Override
    public void releaseTask(LbbMemberRecord record) {
        //返还任务
        TaskComments c = taskCommentsMapper.getByTaskId(record.getTaskId());
        TaskCommentsDetail detail = detailMapper.selectByPrimaryKey(Integer.parseInt(record.getOrderId()));
        detail.setStatus(0);
        detail.setMemberId("");
        detailMapper.updateByPrimaryKeySelective(detail);
        String title = "通用任务释放通知";
        String desc = "任务通知【" + c.getTitle() + "】未在规定时间内完成,已被释放,请重新领取!";
        memberNoticeService.notice(record, title, desc);
        String date = DateUtil.dateToString(new Date(), "yyyyMMdd");
        String creatdate = DateUtil.dateToString(record.getCreateTime(), "yyyyMMdd");
        if (date.equals(creatdate)) {
            taskInRedisService.taskAmountAdd(TASK_COMMENTS_AMOUNT, record.getTaskId());
        }
    }

    @Override
    public boolean starTaskAmount(LocalDateTime dateTime) {
        //每日重载通用任务每日量定时任务方法
        TaskCommentsExample example = new TaskCommentsExample();
        example.createCriteria().andStatusEqualTo(1).andHasDeletedEqualTo(0);
        List<TaskComments> commons = taskCommentsMapper.selectByExample(example);
        redisSdkClient.del(TASK_COMMENTS_AMOUNT);
        List<TaskInitModel> taskInitModels = new ArrayList<>();
        commons.forEach(vo -> {
            TaskInitModel model = new TaskInitModel();
            model.setTaskId(vo.getTaskId());
            model.setAmount(vo.getAmount());
            model.setSuccessTotal(vo.getSuccessCount());
            model.setTodayTotal(vo.getTodayAmount());
            model.setTotal(vo.getTotal());
            taskInitModels.add(model);
        });
        return taskInRedisService.taskInitByTaskModelList(TASK_COMMENTS_AMOUNT, taskInitModels, TaskCategory.Comments, dateTime);
    }

    /**
     * 重载单个任务并且校准成功数
     *
     * @param task
     * @return
     */
    @Override
    public boolean taskInitByTaskId(TaskComments task) {

        int i = lbbMemberRecordMapper.getsuccess(task.getTaskId(), TaskCategory.Comments.name());
        int k = lbbMemberRecordMapper.getfail(task.getTaskId(), TaskCategory.Comments.name());
        task.setSuccessCount(i);
        task.setFailCount(k);
        taskCommentsMapper.updateByPrimaryKeySelective(task);
        TaskInitModel model = new TaskInitModel();
        model.setTaskId(task.getTaskId());
        model.setAmount(task.getAmount());
        model.setSuccessTotal(task.getSuccessCount());
        model.setTodayTotal(task.getTodayAmount());
        model.setTotal(task.getTotal());
        return taskInRedisService.taskInitByTaskModel(TASK_COMMENTS_AMOUNT, model, LocalDateTime.now());
    }
}
